#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string>

#include "socket_utils.h"

using namespace std;

int noblock_send(int fd, const char* buf, int len,unsigned int timeout)
{
    int totalsend = 0;
    int sendlen   = 0;
    struct timeval tstart;
    struct timeval tnow;
    if ( timeout > 0 )
        gettimeofday(&tstart,NULL);
    while(totalsend < len)
    {
        if ( timeout > 0 )
            gettimeofday(&tnow,NULL);

        sendlen = ::send(fd, buf + totalsend,len - totalsend, 0);
        if ( sendlen < 0 )
        {
            if ( timeout > 0 )
            {
                unsigned int msec = 1000*(tnow.tv_sec - tstart.tv_sec) + (tnow.tv_usec - tstart.tv_usec)/1000;
                if ( msec >= timeout )
                    break;
                continue;
            }

            if ( errno == EINTR)
                continue;
            else
                break;
        }
        if ( timeout > 0 )
            tstart = tnow;
        totalsend   += sendlen;
    }

    return totalsend;
}

// 接收完成与否由业务来校验
int noblock_recv(int fd,char* buf,int len, unsigned int timeout)
{
    int total = 0;
    int recvlen = 0;
    struct timeval tstart;
    struct timeval tnow;
    if ( timeout > 0 )
        gettimeofday(&tstart,NULL);
    while( total < len )
    {
        if ( timeout > 0 )
            gettimeofday(&tnow,NULL);

        recvlen = ::recv(fd,buf + total, len - total, 0);
        if ( recvlen < 0)
        {
            if ( timeout > 0 )
            {
                unsigned int msec = 1000*(tnow.tv_sec - tstart.tv_sec) + (tnow.tv_usec - tstart.tv_usec)/1000;
                if ( msec >= timeout )
                    break;
                continue;
            }

            if ( errno == EINTR)
                continue;
            else
                break;
        }
        else if (recvlen == 0)
            break;

        if ( timeout > 0 )
            tstart = tnow;
        total += recvlen;
    }

    return total;
}











